package ee.fj.util.assertion;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.logging.Logger;

public class ComparableAssertion extends Assertion {
	public static final Logger log = Logger.getLogger(ComparableAssertion.class.getName());
	public static enum Type {
		gt, // greater than
		ge, //greater or equals
		eq // equals
	}
	private final String value;
	private final Type type;

	public ComparableAssertion(String value, Type type) {
		this(value, type, DEFAULT_CONDITION);
	}

	public ComparableAssertion(String value, Type type, boolean reverse) {
		super(reverse);
		this.value = value;
		this.type = type;
	}

	private int compare(Object value) {
		if (value instanceof Integer) {
			return ((Integer)value).compareTo(Integer.parseInt(this.value));
		} else if (value instanceof Float) {
			return ((Float)value).compareTo(Float.parseFloat(this.value));
		} else if (value instanceof Long) {
			return ((Long)value).compareTo(Long.parseLong(this.value));
		} else if (value instanceof Short) {
			return ((Short)value).compareTo(Short.parseShort(this.value));
		} else if (value instanceof Double) {
			return ((Double)value).compareTo(Double.parseDouble(this.value));
		} else if (value instanceof BigInteger) {
			return ((BigInteger)value).compareTo(new BigInteger(this.value));
		} else if (value instanceof BigDecimal) {
			return ((BigDecimal)value).compareTo(new BigDecimal(this.value));
		} else if (value instanceof Byte) {
			return ((Byte)value).compareTo(new Byte(this.value));
		}
		return ((Comparable)value).compareTo(this.value);
	}


	@Override
	protected boolean satisfiesInner(Object value) throws AssertionException {
		if (this.value == null && value == null) {
			return true;
		}
		if (value == null)
			return false;

		if (value instanceof Comparable) {
			int rv = compare(value);
			if (type.equals(Type.gt)) {
				return rv < 0;
			} else if (type.equals(Type.ge)) {
				return rv >= 0;
			} else if (type.equals(Type.eq)) {
				return rv == 0;
			}
			System.out.println(value);
		}
		if (type.equals(Type.eq) || type.equals(Type.ge)) {
			return this.value.equals(value.toString());
		} else if (type.equals(Type.gt) || type.equals(Type.ge)) {
			Double d1 = Double.valueOf(this.value);
			Double d2 = Double.valueOf(value.toString());
			if (type.equals(Type.ge)) {
				return d2 >= d1;
			}
			return d2 > d1;
		}

		return false;
	}
}